package com.jianggujin.dbfly.mybatis.xmltag;

import java.util.List;

import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;

import com.jianggujin.dbfly.mybatis.JConfiguration;
import com.jianggujin.dbfly.mybatis.JXMLScriptBuilder;
import com.jianggujin.dbfly.mybatis.dialect.JDialect;
import com.jianggujin.dbfly.util.JDBFlyException;
import com.jianggujin.dbfly.util.dtd.JDTD;
import com.jianggujin.dbfly.util.dtd.JDTDAttribute;
import com.jianggujin.dbfly.util.dtd.JDTDCardinal;
import com.jianggujin.dbfly.util.dtd.JDTDDecl;
import com.jianggujin.dbfly.util.dtd.JDTDElement;
import com.jianggujin.dbfly.util.dtd.JDTDEmpty;
import com.jianggujin.dbfly.util.dtd.JDTDItem;
import com.jianggujin.dbfly.util.dtd.JDTDMixed;
import com.jianggujin.dbfly.util.dtd.JDTDName;
import com.jianggujin.dbfly.util.dtd.JDTDPCData;

/**
 * 函数节点处理器，交由方言处理
 * 
 * @author jianggujin
 *
 */
public class JFnHandler implements JNodeHandler {

    @Override
    public void handleNode(JXMLScriptBuilder builder, XNode nodeToHandle, List<SqlNode> targetContents) {
        JConfiguration configuration = (JConfiguration) builder.getConfiguration();
        JDialect dialect = configuration.getDBFlyConfiguration().getDialect();
        if (!dialect.handleFnNode(builder, nodeToHandle, targetContents)) {
            throw new JDBFlyException("无法解析{}函数标签", nodeToHandle.getName());
        }
    }

    @Override
    public void accept(JDTD dtd) {
        JDTDItem empty = new JDTDEmpty();
        JDTDPCData PCDATA = new JDTDPCData();
        /****** 字符串函数 ******/
        // 参数第一个字符的ASCII码
        dtd.add(new JDTDElement("fn_ascii", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 字符串拼接
        dtd.add(new JDTDElement("fn_concat", new JDTDMixed(new JDTDName("value", JDTDCardinal.ONEMANY))));
        // 返回字符串的字符数
        dtd.add(new JDTDElement("fn_char_length", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 返回字符串的字节数
        dtd.add(new JDTDElement("fn_bit_length", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 返回指定的子字串的位置
        dtd.add(new JDTDElement("fn_position", empty, new JDTDAttribute("sub", "CDATA"),
                new JDTDAttribute("str", "CDATA")));
        // 把字串str里出现地所有子字串from替换成子字串to
        dtd.add(new JDTDElement("fn_replace", empty, new JDTDAttribute("str", "CDATA"),
                new JDTDAttribute("from", "CDATA"), new JDTDAttribute("to", "CDATA")));
        // 从字符串str的start位置截取长度为length的子字符串
        dtd.add(new JDTDElement("fn_sub_str", empty, new JDTDAttribute("str", "CDATA"),
                new JDTDAttribute("start", "CDATA"), new JDTDAttribute("length", "CDATA")));
        // 将字符串转换为大写
        dtd.add(new JDTDElement("fn_upper", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 将字符串转换为小写
        dtd.add(new JDTDElement("fn_lower", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 去掉字符串开始和结尾处的空格
        dtd.add(new JDTDElement("fn_trim", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 去掉字符串开始处的空格
        dtd.add(new JDTDElement("fn_ltrim", PCDATA, new JDTDAttribute("str", "CDATA")));
        // 去掉字符串结尾处的空格
        dtd.add(new JDTDElement("fn_rtrim", PCDATA, new JDTDAttribute("str", "CDATA")));
        /****** 数字函数 ******/
        /****** 日期函数 ******/
        /****** 类型转换函数 ******/
        // 日期格式化
        dtd.add(new JDTDElement("fn_date_format", PCDATA, new JDTDAttribute("format", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("date", "CDATA")));
        // 字符串转日期
        dtd.add(new JDTDElement("fn_str_to_date", PCDATA, new JDTDAttribute("format", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("str", "CDATA")));
        /****** 其他函数 ******/
        dtd.add(new JDTDElement("fn_nvl", empty, new JDTDAttribute("exp1", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("exp2", "CDATA", JDTDDecl.REQUIRED)));
        /****** 辅助标签 ******/
        // 用于分隔参数
        dtd.add(new JDTDElement("value", PCDATA));
        for (String name : MYBATIS_INNER_ELEMENTS) {
            JDTDElement element = dtd.get(name);
            JDTDMixed mixed = (JDTDMixed) element.getContent();
            mixed.add("fn_ascii", "fn_concat", "fn_char_length", "fn_bit_length", "fn_position", "fn_replace",
                    "fn_sub_str", "fn_upper", "fn_lower", "fn_trim", "fn_ltrim", "fn_rtrim", "fn_date_format",
                    "fn_str_to_date", "fn_nvl");
        }
    }
}
